package cn.zj.smart.util;

import cn.zj.smart.util.eo.DateDtf;
import cn.zj.smart.util.exception.ServiceException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.time.*;
import java.time.temporal.WeekFields;

/**
 * 时间处理
 *
 * @author xi.yang
 * @create 2020-11-14 11:04
 **/
public class DateUtil {
    private static final Logger log = LogManager.getLogger(DateUtil.class);
    private static ZoneId zoneId = ZoneId.systemDefault();
    /**
     * 测试偏移时间
     * 毫秒值
     */
    private static long testOffsetTime = 0L;

    public static void initZone(ZoneId zone) {
        zoneId = zone;
    }

    public static void setTestOffsetTime(long offsetTime) {
        testOffsetTime = offsetTime;
    }

    /**
     * localDate转为long
     *
     * @param localDate
     * @return
     */
    public static long localDate2Long(LocalDate localDate) {
        return localDateTime2Long(localDate.atStartOfDay());
    }

    /**
     * localDateTime转long
     *
     * @param localDateTime
     * @return
     */
    public static long localDateTime2Long(LocalDateTime localDateTime) {
        return localDateTime.atZone(zoneId).toInstant().toEpochMilli();
    }

    /**
     * 获取一周的开始时间
     *
     * @param time
     * @return
     */
    public static long getWeekStartTime(long time) {
        LocalDate localDate = long2LocalDate(time);
        int dayOfWeek = localDate.getDayOfWeek().getValue();
        return localDate2Long(localDate.plusDays(-dayOfWeek + 1));
    }

    /**
     * 获取当前时间戳
     *
     * @return
     */
    public static long currentTimeMillis() {
        return localDateTime2Long(curLocalDateTime());
    }

    public static LocalDateTime curLocalDateTime() {
        return LocalDateTime.now(zoneId);
    }

    public static LocalDate curLocalDate() {
        return LocalDate.now(zoneId);
    }

    public static LocalDateTime long2LocalDateTime(long time) {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(time), zoneId);
    }

    public static LocalDate long2LocalDate(long time) {
        return long2LocalDateTime(time).toLocalDate();
    }

    public static LocalDateTime string2LocalDateTime(String timeStr, DateDtf dtf) {
        if (!dtf.isStrProcess()) {
            return LocalDateTime.parse(timeStr, dtf.getFormatter());
        }
        switch (dtf) {
            case MMdd_HHmm:
                return LocalDateTime.parse(curLocalDateTime().getYear() + "-" + timeStr, DateDtf.yyyyMMdd_HHmm.getFormatter());
            case yyyyMM:
                return LocalDate.parse(timeStr + "-" + curLocalDate().getDayOfMonth(), DateDtf.yyyyMMdd.getFormatter()).atStartOfDay();
            case yyyyMMdd:
            case yyyyMMdd_sp:
                // 这些都是直接转日期的
            case yyyyMMdd_ch:
            case yyMMdd_mini:
            case yyyyMMdd_mini:
                return LocalDate.parse(timeStr, dtf.getFormatter()).atStartOfDay();
            case HHmmss:
            case HHmm:
                return LocalTime.parse(timeStr, dtf.getFormatter()).atDate(curLocalDate());
        }
        throw new ServiceException("not define trans dtf [{}]" + dtf);
    }

    public static String long2String(long time, DateDtf dtf) {
        return dtf.getFormatter().format(long2LocalDateTime(time));
    }

    /**
     * 两个时间是否为同一周
     *
     * @param first
     * @param second
     * @return
     */
    private static boolean isSameWeek(LocalDateTime first, LocalDateTime second) {
        return isSameWeek(first.toLocalDate(), second.toLocalDate());
    }

    /**
     * 是否为同一天
     *
     * @param first
     * @param second
     * @return
     */
    private static boolean isSameDay(LocalDate first, LocalDate second) {
        return first.equals(second);
    }

    /**
     * 是否是同月同日
     *
     * @param first
     * @param second
     * @return
     */
    private static boolean isSameMonthDay(LocalDate first, LocalDate second) {
        return MonthDay.of(first.getMonth(), first.getDayOfMonth()).equals(MonthDay.of(second.getMonth(), second.getDayOfMonth()));
    }

    private static final WeekFields weekFields = WeekFields.of(DayOfWeek.MONDAY, 1);

    /**
     * 两个时间是否为同一周
     * 周一是第一天
     * @param first
     * @param second
     * @return
     */
    public static boolean isSameWeek(LocalDate first, LocalDate second) {
        return first.get(weekFields.weekOfWeekBasedYear()) == second.get(weekFields.weekOfWeekBasedYear());
    }
}
